﻿using System;
using System.DirectoryServices;

namespace TechFreak.uapman
{
    /// <summary>
    /// Class to deal with Active Directory
    /// </summary>
    internal static class ActiveDirectory
    {
        /// <summary>
        /// Retrieve an object from Active Directory as <paramref name="returnValue"/>
        /// </summary>
        /// <param name="objectCls">Object Class</param>
        /// <param name="returnValue">Return Value type</param>
        /// <param name="objectName">Object Name to search for</param>
        /// <param name="ldapDomain">Domain to search object in</param>
        /// <returns>Active Directory object of type <paramref name="returnValue"/></returns>
        internal static string GetObjectDistinguishedName(ObjectClass objectCls, ReturnType returnValue, string objectName, string ldapDomain)
        {
            var distinguishedName = string.Empty;
            var connectionPrefix = "LDAP://" + ldapDomain;
            var entry = new DirectoryEntry(connectionPrefix);
            var mySearcher = new DirectorySearcher(entry) { SearchScope = SearchScope.Subtree };

            switch (objectCls)
            {
                case ObjectClass.User:
                    mySearcher.Filter = "(&(objectClass=user)(samAccountName=" + objectName + "))";
                    break;
                case ObjectClass.Group:
                    mySearcher.Filter = "(&(objectClass=group)( | (cn = " + objectName + ")(dn = " + objectName + ")))";
                    break;
                case ObjectClass.Computer:
                    mySearcher.Filter = "(&(objectClass=computer)( | (cn = " + objectName + ")(dn = " + objectName + ")))";
                    break;
            }
            var result = mySearcher.FindOne();

            if (result == null)
            {
                throw new NullReferenceException("unable to locate the distinguishedName for the object " + objectName + " in the " + ldapDomain + " domain");
            }
            var directoryObject = result.GetDirectoryEntry();
            if (returnValue.Equals(ReturnType.DistinguishedName))
            {
                distinguishedName = "LDAP://" + directoryObject.Properties["distinguishedName"].Value;
            }
            if (returnValue.Equals(ReturnType.ObjectGUID))
            {
                distinguishedName = directoryObject.Guid.ToString();
            }
            entry.Close();
            entry.Dispose();
            mySearcher.Dispose();
            return distinguishedName;
        }

        /// <summary>
        /// Retrieves the value of <paramref name="objectDn"/>'s <paramref name="attributeName">Attribute</paramref> as a <see cref="byte"/> array
        /// </summary>
        /// <param name="attributeName">Attribute to retrieve</param>
        /// <param name="objectDn">Object DN to retrieve</param>
        /// <returns><see cref="byte"/> array of <paramref name="attributeName">Attribute</paramref> of <paramref name="objectDn"/></returns>
        internal static byte[] AttributeValuesByteStream(string attributeName, string objectDn)
        {
            var ent = new DirectoryEntry(objectDn);
            var byteValue = (byte[])ent.Properties[attributeName].Value;
            ent.Close();
            ent.Dispose();
            return byteValue;
        }
    }
}
